/*--------------------------------------------------------------------------*/
/*--------------------------------------------------------------------------*/
// winpeg.hpp - Definition file for running PEG on the Win32 Development
//              Platform supporting multiple threads.
//
// Author: Jim DeLisle
//
// Copyright (c) 1997-2002 Swell Software
//              All Rights Reserved.
//
// Unauthorized redistribution of this source code, in whole or part,
// without the express written permission of Swell Software
// is strictly prohibited.
//
// Notes:
//
/*--------------------------------------------------------------------------*/
/*--------------------------------------------------------------------------*/

#ifndef _WINPEG_HPP_
#define _WINPEG_HPP_

/*--------------------------------------------------------------------------*/
// If using WINCE, by default the application will fill the entire screen
// To disable this and allow the application to have a title and
// min, max, and close buttons, disable this configuration
/*--------------------------------------------------------------------------*/
#ifdef PEGWINCE
#define PEG_FULLSIZE_WIN
#endif

#ifdef PEG_MULTITHREAD

/*--------------------------------------------------------------------------*/
// Defines used by the PegPresentationManager to keep track of threads and
// queues.
/*--------------------------------------------------------------------------*/
#define PEG_TASK_TYPE  DWORD
#define PEG_QUEUE_TYPE PegQueue*

/*--------------------------------------------------------------------------*/
// Global reference to the main PEG task. Note that this is a PEGULONG and
// not a HANDLE since GetCurrentThreadId doesn't return a HANDLE. The
// GetCurrentThread function, which does return a HANDLE, is not what we
// want to use for a thread ID since the HANDLE returned is a psuedo HANDLE
// that generally refers to the currently executing thread.
/*--------------------------------------------------------------------------*/
extern PEG_TASK_TYPE PegTaskPtr;

/*--------------------------------------------------------------------------*/
// CriticalSection types that have to be shared with the rest of the
// library.
/*--------------------------------------------------------------------------*/
extern CRITICAL_SECTION PresentationCriticalSection;
extern CRITICAL_SECTION PegTimerCriticalSection;
extern CRITICAL_SECTION PegMessageCriticalSection;

/*--------------------------------------------------------------------------*/
// Replacement PegMessageQueue types and functions
// Note that a thread is assigned a PegQueue and not a PegMessageQueue
// for message passing. In the Win32 model, there is only 1 PegMessageQueue
// instance and it acts as the free message pool for the rest of the
// library/application. A PegQueue retrieves free messages from the pool
// and returns them when they are done.
/*--------------------------------------------------------------------------*/
struct PegMessage;  // forward reference

typedef struct
{
    HANDLE  QueueSem;
    PegMessage *pFirst;
    PegMessage *pLast;
} PegQueue;

void DeleteMessageQueue(PEG_QUEUE_TYPE xchg);
BOOL EnqueueMessage(void *pMesg, PEG_QUEUE_TYPE pQueue);
PEG_QUEUE_TYPE CreateMessageQueue(void);

#define CREATE_MESG_QUEUE            CreateMessageQueue()
#define DELETE_MESSAGE_QUEUE(a)      DeleteMessageQueue(a)
#define ENQUEUE_TASK_MESSAGE(a, b)   EnqueueMessage(a, b)
#define CURRENT_TASK                 GetCurrentThreadId()
#define PEG_TASK_PTR                 PegTaskPtr

/*--------------------------------------------------------------------------*/
// The synchronization functions for protecting the presentation, timer
// and message queues.
/*--------------------------------------------------------------------------*/
#define LOCK_PEG             EnterCriticalSection(&PresentationCriticalSection);
#define UNLOCK_PEG           LeaveCriticalSection(&PresentationCriticalSection);
#define LOCK_TIMER_LIST      EnterCriticalSection(&PegTimerCriticalSection);
#define UNLOCK_TIMER_LIST    LeaveCriticalSection(&PegTimerCriticalSection);
#define LOCK_MESSAGE_QUEUE   EnterCriticalSection(&PegMessageCriticalSection);
#define UNLOCK_MESSAGE_QUEUE LeaveCriticalSection(&PegMessageCriticalSection);

#if defined(PEG_BUILD_PRESS)
/*---------------------------------------------------------------------------*/
// Prototypes and defines if we're building the Peg REmote Screen Server
/*---------------------------------------------------------------------------*/
void LockClientList(void);
void UnlockClientList(void);
void LockPress(void);
void UnlockPress(void);

#define LOCK_CLIENT_LIST            LockClientList();
#define UNLOCK_CLIENT_LIST          UnlockClientList();
#define LOCK_PRESS                  LockPress();
#define UNLOCK_PRESS                UnlockPress();

#endif  // PEG_BUILD_PRESS

#if defined(PEG_BUILD_PRESC)
/*---------------------------------------------------------------------------*/
// Prototypes and defines if we're building the Peg REmote Screen Client
/*---------------------------------------------------------------------------*/
void LockPresc(void);
void UnlockPresc(void);

#define LOCK_PRESC                  LockPresc();
#define UNLOCK_PRESC                UnlockPresc();

#endif  // PEG_BUILD_PRESC

#else

    // here for standalone Win32 build

#define LOCK_PEG
#define UNLOCK_PEG
#define LOCK_MESSAGE_QUEUE
#define UNLOCK_MESSAGE_QUEUE
#define LOCK_TIMER_LIST
#define UNLOCK_TIMER_LIST

#endif  // PEG_MULTITHREAD

#define PEG_DELAY(_timer_ticks_)    Sleep(_timer_ticks_)

#endif  // _WINPEG_HPP_



